home *** CD-ROM | disk | FTP | other *** search
- Subject: v12i034: C News alpha release, Part09/14
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rs@uunet.UU.NET
-
- Submitted-by: utzoo!henry (Henry Spencer)
- Posting-number: Volume 12, Issue 34
- Archive-name: cnews/part09
-
-
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 9 (of 14)."
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'newsbin.proto/maint/arbitron' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'newsbin.proto/maint/arbitron'\"
- else
- echo shar: Extracting \"'newsbin.proto/maint/arbitron'\" \(7860 characters\)
- sed "s/^X//" >'newsbin.proto/maint/arbitron' <<'END_OF_FILE'
- X#! /bin/sh
- X# @(#)arbitron 2.4.2 06/05/87
- X# arbitron -- this program produces rating sweeps for USENET.
- X#
- X# Usage: arbitron
- X#
- X# To use this program, edit the "configuration" section below so that the
- X# information is correct for your site, and then run it. It will produce a
- X# readership survey for your machine and mail that survey to decwrl, with
- X# a cc to you.
- X#
- X# To participate in the international monthly ratings sweeps,
- X# run "arbitron" every month. I will run the statistics program on the last
- X# day of each month; it will include any report that has reached it by that
- X# time. To make sure your site's data is included, run the survey program no
- X# later than the 20th day of each month.
- X#
- X# Brian Reid, DEC Western Research Lab, reid@decwrl
- X# Updated and bugfixed by
- X# Spencer Thomas, U.of Utah
- X# Geoff Kuenning, SAH Consulting
- X# Updated to work with 2.10.1 and older news systems by
- X# Lindsay Cleveland, AT&T Technologies/Bell Labs
- X# Made to work with 16-bit address spaces by
- X# Andy Walker, Maths Dept., University of Nottingham, UK
- X# Nagging Bourne shell bug fixed by
- X# Tom Donahue, Rabbit Software Corp
- X#
- X# Note that the results of this program are dependent on the rate at which
- X# you expire news. If you are a small site that expires news rapidly, the
- X# results may indicate fewer active readers than you actually have.
- X#
- X###########################################################################
- X# Configuration information. Edit this section to reflect your site data. #
- XTMPDIR=/tmp
- XNEWS=/usr/lib/news
- XSPOOL=/usr/spool/news
- X
- X# Make a crude stab at determining the system type. If your installation has
- X# only one type of system, you can edit out the "if" statement and just turn
- X# this into an assignment statement of the correct value.
- Xif [ -d /usr/ucb ]
- Xthen
- X STYPE="bsd"
- Xelse
- X STYPE="usg"
- Xfi
- X
- X# Range of /etc/passwd UID's that represent actual people (rather than
- X# maintenance accounts or daemons or whatever)
- XlowUID=5
- XhighUID=9999
- X
- X# If you aren't running a distributed news system (nntpd & rrn, usually),
- X# leave NEWSHOST blank. Else set it to the name of the host from which you
- X# can rcp a copy of the active file.
- XNEWSHOST=
- X
- X# uucp path: {ihnp4, decvax, ucbvax}!decwrl!netsurvey
- Xsummarypath="netsurvey@decwrl.dec.com $USER"
- X#summarypath="ihnp4!decwrl!netsurvey $USER"
- X
- X# We need to find the uucp name of your host. If this code doesn't work,
- X# then just put it in literally like this:
- X# hostname="ihnp4"
- X
- Xcase $STYPE in
- X bsd) cmd='hostname || uuname -l';;
- X sysv)cmd='uname -n || uuname -l || hostname';;
- X *) cmd='uuname -l';;
- Xesac;
- X
- Xhostname=`sh -c "$cmd" 2>&-`
- X
- XPATH=$NEWS:/usr/ucb:/usr/bin:/bin
- X############################################################################
- Xexport PATH
- X# ---------------------------------------------------------------------------
- Xtrap "rm -f $TMPDIR/arb.*.$$; exit" 0 1 2 3 15
- Xset `date`
- Xdat="$2$6"
- Xdestination="${MAILER-mail} $summarypath"
- X
- X################################
- X# Here are several expressions, each of which figures out approximately how
- X# many people use this machine. Comment out all but 1 of them; pick the one
- X# you like best. Initially the most universal but least reliable of them is
- X# uncommented.
- X# # ###### Scheme #1: fast but usually returns too big a number
- Xnusers=`awk -F: "BEGIN {N=0}\\$3>=$lowUID && \\$3<=$highUID{N=N+1}END{print N}" </etc/passwd`
- X
- X# # ###### Scheme #2 (works with BSD systems)
- X#nusers=`last | sort -u +0 -1 | wc -l`
- X
- X# # ###### Scheme #3 (works with USG systems)
- X#nusers=`who /etc/wtmp | sort -u +0 -1 | wc -l`
- X
- X################################
- X#
- X# Set up awk scripts; these are too large to pass as arguments on most
- X# systems.
- X#
- X# This awk script generates the actual output report.
- X# We use 'sed' to substitute in the shell variables to save ourselves
- X# endless hassle trying to find quoting/backslashing problems.
- X#
- X# The input to this script consists of two types of lines (pre-sorted):
- X#
- X# (1) Active-file lines. These have four fields: newsgroup name,
- X# first existing article, last article number, 'y' or 'n'
- X# to allow/disallow posting.
- X# mod.mac 00001 00001 y
- X#
- X# (2) .newsrc-derived lines. These have three fields: the newsgroup
- X# name, the user name and the articles-read information. The latter
- X# can be arbitrarily complex. It can also be arbitrarily long;
- X# this can potentially break either awk or sed, in which
- X# case the script will not work.
- X# mod.map joe 1-199
- X#
- X# The script uses the type 1 lines to define the newsgroups
- X# and their active article ranges. The .newsrc (type 2) lines are
- X# then used to deduce which users are reading that group (a group
- X# is being read if the last article seen is in that group's active
- X# article range).
- X#
- Xsed "/^#/d
- X s/NUSERS/$nusers/g
- X s/HOSTNAME/$hostname/g
- X s/DATE/$dat/g" > $TMPDIR/arb.fmt.$$ << 'DOG'
- X# makereport -- utility for "arbitron". Early versions were copied from a
- X# similar script distributed with "subscribers.sh" by Blonder, McCreery, and
- X# Herron.
- X#
- X BEGIN { rdrcount = 0 ; reader = "" ; grpcount = 0 ; realusers = 0}
- X#
- X# Active file line: dispose of previous group (if any), record group, and
- X# record first and last article numbers. Set group's reader count to none.
- X NF == 4 { if (grpname != "") {
- X printf("%d %s\n",grpcount, grpname)
- X }
- X grpname = $1
- X grpfirst = $3
- X grplast = $2
- X grpcount = 0
- X }
- X#
- X# .newsrc line. Break out the final number, which is the last article that
- X# has actually been read. This is a pretty good indicator of the person's
- X# true interest in the group. If 'lastread' for the group is a current
- X# (unexpired) article, record a reader for that group. Finally, record
- X# the user as a "real" user of the news system.
- X#
- X NF == 3 { if ($1 != grpname) next;
- X n1 = split($3, n2, "-")
- X n3 = split(n2[n1], n4, ",")
- X lastread = n4[n3]
- X if ((grpfirst != grplast) && (lastread >= grpfirst) && (lastread <= grplast)) {
- X grpcount++
- X if (realuser[$2] != 1) {
- X realuser[$2] = 1
- X realusers++
- X }
- X }
- X }
- X#
- X# End of file. Print the report in 2 columns.
- X END { printf("9999 Host\t\t%s\n","HOSTNAME")
- X printf("9998 Users\t\t%d\n",NUSERS)
- X printf("9997 NetReaders\t%d\n",realusers)
- X printf("9996 ReportDate\t%s\n","DATE")
- X printf("9995 SystemType\tnews-arbitron-2.4\n")
- X# For reorganized network, report a group even if nobody reads it. This will
- X# help us keep track of where the groups propagate.
- X printf("%d %s\n",grpcount, grpname)
- X }
- XDOG
- X
- Xcat >$TMPDIR/arb.pwd.$$ <<'MOUSE'
- XBEGIN { seen["/"]=1; seen[""] = 1; }
- X { if (seen[$6]!=1) {
- X printf("if [ -r %s/.newsrc ] ; then ", $6)
- X printf("sed -n '/: [0-9]/s/:/ %s/p' <%s/.newsrc; fi\n",$1,$6)
- X seen[$6]=1;
- X }
- X}
- XMOUSE
- X
- X# First, make sure we have an active file
- Xif [ -z "$NEWSHOST" ]
- Xthen ACTIVE=$NEWS/active
- Xelse ACTIVE=/tmp/arb.active.$$
- X rcp $NEWSHOST:$NEWS/active $ACTIVE
- Xfi
- X
- Xif [ ! -s $ACTIVE ]
- Xthen
- X echo arbitron: ACTIVE file missing or empty. Cannot continue.
- X exit 1
- Xfi
- X
- X# Next, get the list of .newsrc files with duplicates and unreadable files
- X# removed.
- Xawk -F: -f $TMPDIR/arb.pwd.$$ </etc/passwd | sh >$TMPDIR/arb.tmp.$$
- X
- X# Check to make sure that we found some
- Xif [ -s $TMPDIR/arb.tmp.$$ ]
- Xthen # See if "active" file has 4 fields or only two (pre-2.10.2)
- X set `sed 1q < $ACTIVE`
- X if [ $# -eq 2 ]
- X then egrep '^[a-z]*\.' $ACTIVE |
- X while read group last
- X do dir=`echo "$group" | sed 's;\.;/;g'`
- X first=`ls $SPOOL/$dir | grep '^[0-9]*' | sort -n | sed 1q`
- X case $STYPE in
- X usg) echo "$group $last ${first:-$last} X";;
- X *) echo "$group $last ${first-$last} X"
- X esac
- X done
- X else egrep '^[a-z]*\.' $ACTIVE
- X fi |
- X sort - $TMPDIR/arb.tmp.$$ |
- X awk -f $TMPDIR/arb.fmt.$$ |
- X sort -nr |
- X sed '/^$/d
- X s/^999[0-9] //' |
- X $destination
- Xelse echo Unable to find any readable .newsrc files 2>&1
- X exit 1
- Xfi
- END_OF_FILE
- if test 7860 -ne `wc -c <'newsbin.proto/maint/arbitron'`; then
- echo shar: \"'newsbin.proto/maint/arbitron'\" unpacked with wrong size!
- fi
- # end of 'newsbin.proto/maint/arbitron'
- fi
- if test -f 'rna/man/readnews.1' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rna/man/readnews.1'\"
- else
- echo shar: Extracting \"'rna/man/readnews.1'\" \(7338 characters\)
- sed "s/^X//" >'rna/man/readnews.1' <<'END_OF_FILE'
- X.TH READNEWS 1
- X.SH NAME
- Xnews, readnews \- read news articles
- X.SH SYNOPSIS
- X.B readnews
- X.RB [ -n
- Xnewsgroups]
- X.RB [ -i ]
- X.RB [ -clpC ]
- X.RB [ -s [ -+?
- X.RI [ group ]]]
- X.RB [ -u
- Xmessageid]
- X.SH DESCRIPTION
- X.I Readnews
- Xwithout arguments enters command mode,
- Xwhich allows printing of unread articles.
- XThis is the normal way of using
- X.IR readnews .
- X.P
- X.I Readnews
- Xmaintains a
- X.I .newsrc
- Xfile in the user's home directory that specifies
- Xall news articles already read.
- XIt is updated at the end of each reading session.
- X.P
- XSome useful functions are available which don't use command mode.
- XThe flags for these are:
- X.TP
- X.B -c
- XCheck if there is news, and if so print `You have news.'.
- XA line `readnews -c' is usually placed in the system
- X.I .profile
- X.RB ( /etc/profile ).
- X.TP
- X.B -C
- XCheck if there is news, and print the groups and number of
- Xarticles in each group to be read.
- X.TP
- X.B -l
- XList the titles of available news articles.
- X.TP
- X.B -p
- XPrint all articles on standard output,
- Xand update
- X.IR newsrc .
- X.TP
- X.B -s
- XPrint the newsgroup subscription list.
- X.TP
- X.BI -s+ " group"
- XAdd
- X.I group
- Xto the subscription list.
- X.TP
- X.BI -s- " group"
- XSubtract
- X.I group
- Xfrom the subscription list.
- X.TP
- X.B -s?
- XList currently active newsgroups.
- X.P
- XThe remaining flags determine article selection,
- Xand may also appear in the
- X.I .newsrc
- Xfile.
- XOptions may be specified in the
- X.I .newsrc
- Xfile by entering lines prefixed with the word `options',
- Xfollowed by the options arguments.
- XThis is most useful with the
- X.B -n
- Xflag, specifying the usual groups one wishes to subscribe to.
- X.TP
- X\fB-n \fInewsgroups\fR
- XSelect all articles belonging to
- X.IR newsgroups .
- X.I newsgroups
- Xis a comma separated list of newsgroup names.
- XThe character `!' may be used to exclude certain groups,
- Xand the word `all' can be used to match any group.
- Xe.g. `-n all,!net.jokes'
- X.TP
- X.B -i
- XIgnore
- X.I .newsrc
- Xfile. It is not read or updated.
- XThis allows selection of articles that have already been read.
- X.TP
- X\fB-u \fImessageid\fR
- XUnsubscribe to followup articles referring to
- X.IR messageid .
- X(This flag is usually only placed in the
- X.I .newsrc
- Xfile as a result of the `u' command.)
- X.SH COMMANDS
- XThis section details the commands available when
- X.I readnews
- Xis in command mode (no
- X.B -clpsC
- Xarguments).
- XThe simplest way of using this mode, is to enter RETURN after every
- Xprompt.
- XThis will present to the user, a short heading for an article, then a prompt.
- XTyping RETURN again will print the article body.
- XTyping RETURN yet again will print the next heading, and so on.
- XIf having read the heading, you don't wish to read the article, you may
- Xtype `n' (or `+' or ';') which will take you directly to the next heading.
- X.P
- X.P
- XAn article is treated as having been read, if either you have seen
- Xthe article body, or typed `n' to skip over it.
- X.P
- XA number of commands operate on the `current' article.
- XThis is defined as the article whose header you have most recently seen.
- X.P
- XThe commands to read news are:
- X.TP
- X.B RETURN
- XEither print the current article,
- Xor go to the next article and print its header.
- X.TP
- X\fBn\fR or \fB+\fR or \fB;\fR
- XGo to the next article and print its header.
- X.TP
- X.B .
- XPrint the current article.
- X.TP
- X.B -
- XGo back to the previous article. This is a toggle, typing it
- Xtwice returns you to the original article.
- X.TP
- X.I number
- XGo to the article
- X.I number
- Xin the current newsgroup.
- XLike the `-' command,
- Xyou always return to the original article
- Xafter reading the selected article.
- X.TP
- X\fBs \fR[\fIfile\fR]
- XSave the current article, either in the specified file, or
- Xin
- X.BR $HOME/articles .
- X.TP
- X.B h
- XPrint the current header (slightly more verbose than normal header).
- X.TP
- X.B H
- XPrint the current header in full (very verbose).
- X.TP
- X\fBN \fR[\fInewsgroup\fR]
- XGo to the next newsgroup, or to the specified newsgroup.
- X.TP
- X.B u
- XUnsubscribe from all further followup articles on this topic.
- X.TP
- X.B U
- XUnsubscribe from this newsgroup, and go to the next newsgroup.
- X.TP
- X\fB!\fIcommand\fB
- XShell escape.
- X.I Command
- Xis executed.
- XIf
- X.I command
- Xis `!'
- Xthe last escape command is executed.
- X.TP
- X\fBq\fR or \fBEOT\fR
- XQuit.
- XThe
- X.I .newsrc
- Xfile will be updated provided the flag
- X.B -i
- Xwas not specified.
- X.TP
- X.B x
- XExit.
- X.I .newsrc
- Xis left unchanged (as if no articles had been read).
- X.TP
- X.B DEL
- XAn interrupt will cause
- X.I readnews
- Xto terminate its current activity and return to command mode.
- XAn interrupt in command mode will cause `Interrupt' to be printed,
- Xand a subsequent interrupt will cause immediate exit (as in the `x' command).
- X.P
- XSome commands are available to send/reply or cancel news articles:
- X.TP
- X.B c
- XCancel article. Only the author, or news administrator can do this.
- X.IR postnews (1)
- Xis called to do the actual cancelling.
- X.TP
- X.B r
- XReply to sender of the current article by mail.
- X.I Readnews
- Xsets up the appropriate headers, and then calls
- X.IR mail (1)
- Xto send a reply to the sender.
- X.TP
- X.B f
- XPost a followup to the current article.
- X.I Readnews
- Xsets up the appropriate headers, and then calls
- X.IR postnews (1)
- Xto post the followup article.
- X.TP
- X.B p
- XPost an article on a new topic.
- X.IR postnews (1)
- Xis called to post the new article.
- X.TP
- X\fBm \fIperson\fB
- XMail to
- X.IR person .
- X.P
- XWhen replying by mail, or posting an article, the user
- Xis prompted for certain headers, and then the text of the article or mail
- Xitem is entered until a `.' or EOT is entered alone on a line.
- XThen the article/mail is posted/mailed.
- XOther commands are available:
- X.TP
- X\&\fB.e\fR
- XEdit the message/article collected so far (see
- X.IR ed (1)).
- XThe 'To:' or 'cc:' fields may be changed if mailing.
- XAfter editing further lines may be appended to the message.
- X.TP
- X\&\fB.i\fR
- XInterpolate
- Xthe current news article onto the end of the message.
- XThe interpolated item
- Xis indented by four spaces.
- X.TP
- X\&\fB.!\fIcmd\fR or \fB!\fIcmd\fR
- XShell escape.
- X.IR Cmd
- Xis executed.
- X.TP
- X.B DEL
- XCauses posting/mailing to be aborted, and the article entered so far
- Xis saved in
- X.B $HOME/dead.article
- Xor
- X.BR $HOME/dead.letter .
- X.P
- XIn order to permanently resubscribe to a newsgroup denied by `U',
- Xor a series of followups denied by `u' it is necessary to understand
- Xthe format of the
- X.I .newsrc
- Xfile.
- XThe
- X.I .newsrc
- Xfile consists of two types of lines:
- X.TP
- Xoption lines
- XThese start with the word `option' and contain the same arguments
- Xas the
- X.I readnews
- Xcommand on the command line.
- XFollowups are denied with `option -u <messageid>'.
- XTo resubscribe to further followups, the correct options line must be deleted.
- X.TP
- Xread newsgroup lines
- XThese have the format <newsgroup>`:' <number>, where
- X<number> represents the last item number seen in that particular newsgroup.
- XIf the newsgroup has been unsubscribed, the `:' is replaced by a `!'.
- XTo resubscribe the `!' must be changed back to a `:'.
- X.SH FILES
- X.ta 24
- X.nf
- X$HOME/.newsrc options and list of previously read articles
- X%news where the articles are kept
- X/usr/lib/news/active current newsgroups
- X/usr/lib/news/help help file
- X.fi
- X.SH SEE ALSO
- Xpostnews(1), mail(1), ed(1), uusend(8), uurec(8).
- X.SH BUGS
- X.I Readnews
- Xwith the
- X.B -c
- Xflag may say "You have news.", when the available article is a unsubscribed
- Xfollowup article.
- X.P
- XYou may see followups, even if you have used the `u' command.
- XThis is because many sites have faulty news programs, which do
- Xnot follow the correct protocol, or the sender did not use the `r' command.
- X.SH AUTHOR
- XMichael Rourke, University of N.S.W (decvax!mulga!michaelr:elecvax)
- END_OF_FILE
- if test 7338 -ne `wc -c <'rna/man/readnews.1'`; then
- echo shar: \"'rna/man/readnews.1'\" unpacked with wrong size!
- fi
- # end of 'rna/man/readnews.1'
- fi
- if test -f 'rna/newsrc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rna/newsrc.c'\"
- else
- echo shar: Extracting \"'rna/newsrc.c'\" \(6581 characters\)
- sed "s/^X//" >'rna/newsrc.c' <<'END_OF_FILE'
- X/*
- X * newsrc file handling
- X */
- X
- X#include "defs.h"
- X
- Xstatic char nrcname[] = NEWSRC;
- X
- Xstatic char *rcname; /* full pathname of .newsrc */
- Xnewsrc *rc; /* internal .newsrc */
- Xchar *rcgrps; /* subscription from .newsrc */
- Xstatic newsrc *lastrc; /* last newsrc struct in list */
- Xstatic int rclineno; /* current lineno in .newsrc */
- Xstatic bool sortrc; /* if we should sort on output */
- X
- Xstatic newsrc *findnewsrc();
- X
- Xreadnewsrc()
- X{
- X register FILE *f;
- X static char option[] = "options";
- X char word[BUFSIZ], rest[BUFSIZ];
- X extern char *getenv();
- X
- X if ((rcname = getenv("HOME")) == NULL)
- X error("No $HOME in environment.");
- X rcname = newstr3(rcname, "/", nrcname);
- X if ((f = fopen(rcname, "r")) == NULL)
- X return;
- X
- X rclineno = 0;
- X while (getline(f, word, rest))
- X if (CMP(word, option) == 0)
- X dooptions(rest);
- X else
- X dorcline(word, rest);
- X (void) fclose(f);
- X}
- X
- X/*
- X * Read a line from f, put first word into w and the rest into r.
- X * Discard trailing newline instead of storing it.
- X * This is a poor design, as w & r are unchecked for overrun.
- X */
- Xstatic
- Xgetline(f, w, r)
- Xregister FILE *f;
- Xchar *w, *r;
- X{
- X register int c;
- X register char *s;
- X
- X rclineno++;
- X s = w;
- X while ((c = getc(f)) != EOF && c != ' ' && c != '\t')
- X *s++ = c; /* stash first word */
- X *s = '\0';
- X
- X if (c != EOF) {
- X s = r;
- X while ((c = getc(f)) != EOF && c != '\n')
- X *s++ = c; /* stash the rest */
- X *s = '\0';
- X }
- X
- X if (c != '\n' && c != EOF)
- X error("Bad format: %s line %d: %s", rcname, rclineno, w);
- X
- X return c != EOF;
- X}
- X
- X/*
- X * Parse s into words and simulate command line arguments with them.
- X */
- Xstatic
- Xdooptions(s)
- Xchar *s;
- X{
- X register char *cp;
- X register int argc;
- X register char **argv;
- X
- X cp = s;
- X while (isspace(*cp))
- X cp++;
- X if (!*cp)
- X return;
- X
- X argc = 1;
- X argv = (char **) myalloc(sizeof(char *));
- X argv[argc - 1] = cp;
- X while (*cp && (cp = strpbrk(cp, " \t")) != NULL) {
- X while (*cp == ' ' || *cp == '\t')
- X *cp++ = '\0';
- X if (*cp) {
- X argc++;
- X argv = (char **) myrealloc((char *) argv,
- X argc * (int)sizeof(char *));
- X argv[argc - 1] = cp;
- X }
- X }
- X if (options(argc, argv, false))
- X error("Bad options: %s line %d: %s", rcname, rclineno, s);
- X free((char *) argv);
- X}
- X
- X/*
- X * Parse w & r together as a .newsrc newsgroup line.
- X */
- Xstatic
- Xdorcline(w, r)
- Xchar *w, *r;
- X{
- X register char lastw;
- X register int len;
- X register newsrc *np;
- X
- X len = strlen(w);
- X lastw = w[len - 1]; /* save presumed colon or bang */
- X w[len - 1] = '\0'; /* nuke presumed colon */
- X while (*r == ' ' || *r == '\t')
- X r++; /* skip extra whitespace */
- X
- X /* kludges, hacks, etc. for compatibility with other readers */
- X if (strncmp(r, "1-", sizeof "1-"-1) == 0)
- X r += sizeof "1-"-1; /* skip usual `1-' */
- X if (*r == '\0') /* rn's: `news.trash: ' */
- X r = "0"; /* fake a zero */
- X
- X if (lastw != ':' && lastw != NEGCHAR || !isdigit(*r))
- X error("Bad line: %s line %d: %s", rcname, rclineno, w);
- X
- X np = NEW(newsrc);
- X np->n_subscribe = (bool) (lastw == ':'); /* colon or bang? */
- X np->n_next = NIL(newsrc);
- X np->n_last = atoi(r); /* stash first number only */
- X np->n_name = newstr(w); /* stash n.g. name */
- X
- X if (rc == 0)
- X rc = np;
- X else
- X lastrc->n_next = np;
- X lastrc = np;
- X}
- X
- X/*
- X * for every group in active list, which belongs to the specified subscription
- X * list, and has messages to be read, call func
- X * if no mention in newsrc file, make new entry
- X */
- Xapply(alist, group, func, dolast)
- Xactive *alist;
- Xchar *group;
- Xapplycom (*func)();
- Xbool dolast;
- X{
- X register active *ap;
- X register newsrc *np;
- X register applycom act;
- X register bool donesome;
- X
- X donesome = false;
- X do {
- X act = stop;
- X for (ap = alist; ap; ap = ap->a_next) {
- X if (ap->a_seq == 0 || ap->a_low > ap->a_seq)
- X continue; /* empty group */
- X if (!ngmatch(ap->a_name, group))
- X continue;
- X if ((np = findnewsrc(ap->a_name)) == NIL(newsrc)) {
- X np = NEW(newsrc);
- X np->n_name = newstr(ap->a_name);
- X np->n_next = NIL(newsrc);
- X np->n_last = 0;
- X np->n_subscribe = true;
- X if (!rc)
- X rc = np;
- X else
- X lastrc->n_next = np;
- X lastrc = np;
- X }
- X if (!np->n_subscribe)
- X continue;
- X /*
- X * if we haven't read any news for a while (or at all),
- X * or somehow seq got smaller (active corrupted?),
- X * set last read to oldest available article
- X */
- X if (ap->a_low - 1 > np->n_last || ap->a_seq < np->n_last)
- X np->n_last = ap->a_low - 1;
- X while (np->n_last < ap->a_seq) {
- X donesome = true;
- X switch (act = (*func)(ap, np, false, false)) {
- X case stop:
- X return;
- X case next:
- X continue;
- X case nextgroup:
- X break;
- X case searchgroup:
- X break;
- X }
- X break;
- X } /* while */
- X if (act == searchgroup)
- X break;
- X } /* for */
- X if (act != searchgroup && dolast && donesome)
- X act = (*func)(NIL(active), NIL(newsrc), true, false);
- X } while (act == searchgroup);
- X}
- X
- X/*
- X * find if a newrc entry exists,
- X * taking advantange of the fact that requests should be
- X * in the same order
- X *
- X * detect when the newsrc gets out of order
- X * so it can be sorted at the end of the session
- X */
- Xstatic newsrc *
- Xfindnewsrc(name)
- Xregister char *name;
- X{
- X register newsrc *np, *start;
- X register bool found;
- X static newsrc *nextp;
- X
- X if (!rc)
- X return NIL(newsrc);
- X
- X found = false;
- X np = nextp ? nextp : rc;
- X nextp = start = np;
- X do {
- X if (CMP(np->n_name, name) == 0) {
- X found = true;
- X break;
- X }
- X np = np->n_next;
- X if (!np)
- X np = rc;
- X } while (np != nextp);
- X
- X if (!found)
- X return NIL(newsrc);
- X nextp = np->n_next;
- X if (np != start)
- X sortrc = true;
- X return np;
- X}
- X
- X/*
- X * rewrite the newsrc file
- X */
- Xwritenewsrc(alist)
- Xactive *alist;
- X{
- X register FILE *f;
- X register active *ap;
- X register newsrc *np;
- X register int i;
- X extern char **uflag;
- X extern int usize;
- X
- X if (!rc && !uflag && (!rcgrps || !*rcgrps))
- X return;
- X
- X signal(SIGINT, SIG_IGN);
- X signal(SIGQUIT, SIG_IGN);
- X
- X f = fopenf(rcname, "w");
- X if (rcgrps && *rcgrps)
- X (void) fprintf(f, "options -n %s\n", rcgrps);
- X if (uflag) {
- X scanhist(uflag, usize); /* forget id's not in history */
- X for (i = 0; i < usize; i++) /* print whats left */
- X if (uflag[i])
- X (void) fprintf(f, "options -u %s\n", uflag[i]);
- X }
- X if (sortrc) {
- X /*
- X * sort newsrc so next time we use it,
- X * history/newsrc comparisons will be faster
- X */
- X for (ap = alist; ap; ap = ap->a_next)
- X if (np = findnewsrc(ap->a_name))
- X writengline(f, np);
- X } else
- X for (np = rc; np; np = np->n_next)
- X writengline(f, np);
- X (void) fclose(f);
- X}
- X
- Xstatic
- Xwritengline(f, np) /* write .newsrc n.g. line in normal form on f */
- Xregister newsrc *np;
- X{
- X (void) fprintf(f, "%s%c 1-%d\n", np->n_name,
- X (np->n_subscribe? ':': NEGCHAR), np->n_last);
- X}
- END_OF_FILE
- if test 6581 -ne `wc -c <'rna/newsrc.c'`; then
- echo shar: \"'rna/newsrc.c'\" unpacked with wrong size!
- fi
- # end of 'rna/newsrc.c'
- fi
- if test -f 'rnews/fileart.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rnews/fileart.c'\"
- else
- echo shar: Extracting \"'rnews/fileart.c'\" \(6901 characters\)
- sed "s/^X//" >'rnews/fileart.c' <<'END_OF_FILE'
- X/*
- X * fileart - file an article, given its temp file name and its headers
- X * TODO: change in junk policy, suggested by gnu (has this been done already?):
- X * 3 classes of ng: wanted, not wanted (!ng in sys -> ignore it),
- X * don't know it (not in active -> change to junk).
- X * TODO: clean up packaging of fileart: push the 3-arg open caller into vers/*?
- X */
- X
- X#include <stdio.h>
- X#include <errno.h>
- X#include <sys/types.h>
- X
- X#include "fcntl.h" /* try to define O_* and F_* */
- X
- X#include "news.h"
- X#include "newspaths.h"
- X#include "active.h"
- X#include "headers.h"
- X#include "system.h"
- X
- X#ifndef F_OK
- X#define F_OK 0
- X#endif
- X
- X#define JUNK "junk" /* name of lost+found ng. */
- X#define CONTROL "control"
- X
- Xstatic long artnum; /* asgnartnum sets artnum */
- Xstatic int goodngs; /* asgnartnum reads goodngs */
- X
- Xstatic int debug = NO;
- X
- Xfiledebug(state) /* set debugging state */
- Xint state;
- X{
- X debug = state;
- X}
- X
- X/*
- X * TODO: new proposed junk policy:
- X * delay until the end, then file *once* in junk if any ngs
- X * were not in active but were in sys file subscription list.
- X */
- X/*
- X * File the article in "*tfp" in the spool directory.
- X * hdrs are the associated headers. fileart fills in hdrs->h_files too.
- X *
- X * If openfirst is true, fill in h_tmpf with the name of the first link,
- X * fopen it (into *tfp), and make any remaining links.
- X * openfirst really means "Newsgroups:" has been seen.
- X * Generates Xref: header if needed.
- X */
- Xint
- Xfileart(hdrs, tfp, openfirst)
- Xregister struct headers *hdrs;
- XFILE **tfp;
- Xint openfirst;
- X{
- X register char *comma;
- X int status = ST_OKAY;
- X char *ng; /* point at current newsgroup */
- X char artnumstr[MAXCOMP]; /* article number in ascii */
- X char group[MAXFILE]; /* a group */
- X
- X if (hdrs->h_filed)
- X return status;
- X artnum = 0;
- X goodngs = 0;
- X /*
- X * Store in spooldir.
- X * Link temp file to spooldir/ng/article-number for each ng.
- X */
- X for (ng = hdrs->h_ngs; ng != NULL; ng = comma) {
- X int lstatus = ST_OKAY;
- X
- X comma = index(ng, NGSEP);
- X if (comma != NULL)
- X *comma = '\0'; /* restored below */
- X if (hdrs->h_ctlcmd != NULL) /* ctl. msg.s go in CONTROL */
- X (void) strcpy(group, CONTROL);
- X else
- X (void) strcpy(group, ng); /* copy out newsgroup name */
- X if (comma != NULL)
- X *comma++ = NGSEP; /* step past comma */
- X
- X lstatus |= asgnartnum(hdrs, tfp, openfirst, group, artnumstr);
- X /*
- X * No such group in active or link failed but our
- X * subscription list permits this group,
- X * so file it under "junk", if it exists.
- X */
- X if ((artnum < 1 || lstatus != ST_OKAY) &&
- X ngmatch(oursys()->sy_ngs, group)) {
- X (void) strcpy(group, JUNK);
- X lstatus = asgnartnum(hdrs, tfp, openfirst,
- X group, artnumstr);
- X /*
- X * You could set ST_DROPPED here if you think
- X * one might accidentally not have "junk"
- X * in active. I tend to think the absence
- X * of "junk" would be deliberate, to prevent
- X * filing of junk articles.
- X */
- X if (artnum < 1 || lstatus != ST_OKAY)
- X lstatus |= ST_NUKED; /* no junk ng */
- X }
- X if (artnum >= 1 && lstatus == ST_OKAY) {
- X /*
- X * Article # was assigned and the link succeeded.
- X * Update hdrs->h_files list for history.
- X */
- X hdrs->h_filed = YES; /* make a note */
- X if (hdrs->h_files[0] != '\0')
- X (void) strcat(hdrs->h_files, " ");
- X (void) strcat(hdrs->h_files, group); /* normal case */
- X (void) strcat(hdrs->h_files, SFNDELIM);
- X (void) strcat(hdrs->h_files, artnumstr);
- X ++goodngs;
- X }
- X status |= lstatus & ~ST_NUKED;
- X }
- X /*
- X * No good ngs if article was accepted by our subscription list,
- X * yet none of the groups are in our active file
- X * (e.g. net.rec.drugs,net.chew-the-fat) & no junk group exists.
- X *
- X * TODO: could call asgnartnum here instead. Hmmm...
- X * Current policy makes a junk link for each bad group,
- X * this would instead make one junk link, no matter how
- X * many bad groups, and only if all are bad.
- X * But we want to know *why* there are no good ngs; it could
- X * be because they are all denied by our subscription list.
- X * Again, could set ST_DROPPED here (no junk group).
- X */
- X if (goodngs == 0)
- X status |= ST_NUKED; /* TODO: complain: no good ngs? */
- X else if (goodngs > 1 && *tfp != NULL) /* cross-posted? */
- X status |= emitxref(*tfp, hdrs);
- X return status;
- X}
- X
- X/*
- X * Assign a permanent name and article number to the temporary name hdrs->h_tmpf
- X * in newsgroup "ng" & store the ascii form of the article number into "artnumstr",
- X * returning the article number in "artnum".
- X *
- X * If openfirst is true and goodngs is zero, set inname to artname,
- X * fopen artname and store the result through tfp.
- X */
- Xstatic int
- Xasgnartnum(hdrs, tfp, openfirst, ng, artnumstr)
- Xstruct headers *hdrs;
- XFILE **tfp;
- Xint openfirst;
- Xchar *ng;
- Xchar *artnumstr;
- X{
- X register int status = ST_OKAY;
- X char *inname = hdrs->h_tmpf;
- X char slashng[MAXFILE]; /* a group, slashed */
- X extern int errno;
- X
- X#define openorlink(inname, artname, tfp, openfirst, goodngs) \
- X (openfirst && goodngs == 0? openlink(inname, artname, tfp): \
- X link(inname, artname) == 0)
- X
- X (void) strcpy(slashng, ng);
- X mkfilenm(slashng);
- X while ((artnum = nxtartnum(ng)) >= 1) {
- X char artname[MAXFILE]; /* article file name */
- X
- X (void) strcpy(artname, slashng);
- X (void) strcat(artname, SFNDELIM);
- X (void) sprintf(artnumstr, "%ld", artnum);
- X (void) strcat(artname, artnumstr);
- X
- X /*
- X * we changed directory to spooldir in main(),
- X * so artname is relative to spooldir,
- X * therefore artname can be used as is.
- X */
- X#ifdef notdef
- X (void) strcpy(artname, spoolfile(artname));
- X#endif
- X
- X if (debug && !(openfirst && goodngs == 0))
- X (void) fprintf(stderr, "about to link %s to %s... ",
- X inname, artname);
- X if (openorlink(inname, artname, tfp, openfirst, goodngs)) {
- X if (debug)
- X (void) fprintf(stderr, "success!\n");
- X break; /* link succeeded */
- X } else {
- X /*
- X * Link failed. Maybe some directories are missing,
- X * so create any missing directories and try again.
- X */
- X if (debug)
- X warning("failed!", "");
- X (void) checkdir(artname, getuid(), getgid());
- X if (openorlink(inname, artname, tfp, openfirst, goodngs))
- X break; /* link succeeded this time */
- X else if (errno != EEXIST) {
- X warning("can't link to %s", artname);
- X status |= ST_DROPPED;
- X break;
- X }
- X /*
- X * Else artname exists. It must be a numeric subgroup name,
- X * such as net.micro.432; try another article.
- X */
- X }
- X }
- X return status;
- X}
- X
- X/*
- X * Open artname, save the name on sp & the FILE pointer through tfp.
- X */
- Xstatic int
- Xopenlink(sp, artname, tfp)
- Xchar *sp;
- Xchar *artname;
- XFILE **tfp;
- X{
- X (void) strcpy(sp, artname); /* save a copy */
- X#ifdef O_EXCL
- X /* This is the cheaper way. */
- X {
- X int fd = open(sp, O_WRONLY|O_CREAT|O_EXCL, 0666);
- X
- X if (fd < 0)
- X *tfp = NULL;
- X else
- X *tfp = fdopen(fd, "w");
- X }
- X#else
- X if (access(sp, F_OK) >= 0) /* sp exists */
- X *tfp = NULL; /* refuse to write on it */
- X else
- X *tfp = fopen(sp, "w"); /* try to create it */
- X#endif
- X return *tfp != NULL;
- X}
- END_OF_FILE
- if test 6901 -ne `wc -c <'rnews/fileart.c'`; then
- echo shar: \"'rnews/fileart.c'\" unpacked with wrong size!
- fi
- # end of 'rnews/fileart.c'
- fi
- if test -f 'rnews/procart.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rnews/procart.c'\"
- else
- echo shar: Extracting \"'rnews/procart.c'\" \(7574 characters\)
- sed "s/^X//" >'rnews/procart.c' <<'END_OF_FILE'
- X/*
- X * process a single incoming article
- X */
- X
- X#include <stdio.h>
- X#include <sys/types.h>
- X#include "news.h"
- X#include "active.h"
- X#include "headers.h"
- X#include "system.h"
- X
- X#ifndef COPYSIZE
- X#ifdef pdp11
- X#define COPYSIZE BUFSIZ
- X#else
- X#define COPYSIZE 8192
- X#endif /* pdp11 */
- X#endif /* COPYSIZE */
- X
- Xextern char *exclude; /* for erik */
- X
- X/*
- X * Copy the article on "in" to a temporary name in the news spool directory,
- X * unlink temp name; *or* copy into the final names, if known earlier enough.
- X * (Sets h_tmpf in or near mungehdrs() or hdrdump().)
- X * If the spool file opened, install the article it contains.
- X */
- Xint
- Xcpinsart(in, inname, maxima)
- XFILE *in;
- Xchar *inname;
- Xlong maxima;
- X{
- X int status = ST_OKAY;
- X FILE *tf = NULL;
- X struct headers hdrs;
- X
- X hdrinit(&hdrs);
- X status |= copyart(in, inname, maxima, &tf, &hdrs);
- X if (status&ST_NUKED) { /* no good ngs (in fileart) */
- X char *msgid = "", *ngs = "";
- X
- X status &= ~ST_NUKED; /* nuking isn't serious */
- X if (hdrs.h_msgid != NULL)
- X msgid = hdrs.h_msgid; /* caution */
- X if (hdrs.h_ngs != NULL)
- X ngs = hdrs.h_ngs; /* caution */
- X timestamp(stdout, (time_t *)NULL, (char **)NULL);
- X (void) printf(" refused %s bad groups in `%s' and no junk group\n",
- X msgid, ngs);
- X } else if (tf == NULL) {
- X warning("can't open spool file `%s'", hdrs.h_tmpf);
- X status |= ST_DROPPED;
- X } else {
- X status |= insart(tf, &hdrs);
- X (void) fclose(tf);
- X }
- X freeheaders(&hdrs);
- X return status;
- X}
- X
- X/*
- X * Copy the next charcnt bytes of "in" (may be not a disk file)
- X * to a permanent file under a (possibly) temporary name.
- X * Must munge certain headers on the way & remember certain values.
- X * mungehdrs() or hdrdump() sets hdrs->h_tmpf & *tfp.
- X */
- X/* ARGSUSED inname */
- Xstatic int
- Xcopyart(in, inname, charcnt, tfp, hdrs)
- Xregister FILE *in;
- Xchar *inname;
- Xregister long charcnt;
- Xregister FILE **tfp;
- Xstruct headers *hdrs;
- X{
- X register int readcnt;
- X int status = ST_OKAY;
- X char *s = NULL;
- X char line[COPYSIZE];
- X
- X hdrwretch(); /* reset the header parser */
- X /*
- X * people think this loop is ugly; not sure why.
- X * if the byte count is positive, read a line; if it doesn't return
- X * EOF and is a header, then adjust byte count, eat and munge headers.
- X * strlen(line) must be computed before hdrmutate is called, as it
- X * removes newlines.
- X */
- X while (charcnt > 0 &&
- X (s = fgets(line, (int)min(sizeof line-1, charcnt)+1, in)) != NULL
- X && ishdr(line)) {
- X charcnt -= strlen(line);
- X status |= hdrmutate(hdrs, line, tfp); /* eat & munge headers */
- X /* hdrdump() counts hdrs->h_charswritten */
- X }
- X hdrdeflt(hdrs);
- X
- X /* write any saved headers, trigger fileart */
- X status |= hdrdump(tfp, hdrs, YES);
- X
- X /* Copy first body line. */
- X if (charcnt > 0 && s != NULL) { /* fgets worked: not a header line */
- X register int linelen = strlen(line);
- X
- X if (*tfp != NULL && fputs(line, *tfp) == EOF)
- X status = fulldisk(status|ST_DROPPED,
- X (hdrs->h_unlink? hdrs->h_tmpf: hdrs->h_files));
- X charcnt -= linelen;
- X hdrs->h_charswritten += linelen;
- X }
- X /*
- X * Copy at most "sizeof line" bytes at a time
- X * and exactly charcnt bytes in total, barring EOF.
- X */
- X for (; charcnt > 0 && !(status&ST_DISKFULL) &&
- X (readcnt=fread(line, 1, (int)min(charcnt, sizeof line), in)) > 0;
- X charcnt -= readcnt, hdrs->h_charswritten += readcnt)
- X if (*tfp != NULL && fwrite(line, 1, readcnt, *tfp) != readcnt)
- X status = fulldisk(status|ST_DROPPED,
- X (hdrs->h_unlink? hdrs->h_tmpf: hdrs->h_files));
- X if (*tfp != NULL && fflush(*tfp) == EOF) /* force to disk */
- X status = fulldisk(status|ST_DROPPED,
- X (hdrs->h_unlink? hdrs->h_tmpf: hdrs->h_files));
- X if (charcnt > 0 && remote) { /* TODO: don't use "remote" */
- X (void) fprintf(stderr, "%s: article %s short by %ld bytes\n",
- X progname, (hdrs->h_msgid != NULL? hdrs->h_msgid: ""),
- X (long)charcnt);
- X status |= ST_SHORT; /* N.B.: do not uninstall this article */
- X }
- X return status;
- X}
- X
- X/*
- X * Read headers from "in".
- X * Iff we haven't seen this article already and we like the groups,
- X * install the article on "in" & hdrs->h_tmpf.
- X * Rename hdrs->h_tmpf into the news spool directory.
- X * Add history entries for the article.
- X * Transmit the article, like a dose of clap, to our neighbours.
- X * Process control mess(age)es.
- X * Unlink hdrs->h_tmpf, if a temporary link.
- X */
- Xstatic int
- Xinsart(in, hdrs)
- XFILE *in;
- Xstruct headers *hdrs;
- X{
- X register int status = ST_OKAY;
- X
- X status |= reject(hdrs);
- X if (status&(ST_DROPPED|ST_NUKED))
- X uninsart(hdrs); /* remove existing links; give back assigned #s */
- X else {
- X /*
- X * Ordinary filing: if not already filed,
- X * make links to hdrs->h_tmpf (which will exist).
- X */
- X status |= fileart(hdrs, &in, 0); /* generates Xref: */
- X if (!(status&(ST_DROPPED|ST_NUKED))) {
- X status |= history(hdrs); /* writes "received: " */
- X /* writes systems on stdout */
- X status |= transmit(hdrs, remote, exclude);
- X (void) putc('\n', stdout); /* ends the line */
- X (void) fflush(stdout); /* crash-proofness */
- X if (hdrs->h_ctlcmd != NULL)
- X status |= ctlmsg(hdrs);
- X }
- X }
- X status &= ~ST_NUKED; /* nuking is quite casual */
- X if (hdrs->h_unlink && unlink(hdrs->h_tmpf) < 0) {
- X warning("can't unlink `%s'", hdrs->h_tmpf);
- X status |= ST_ACCESS;
- X }
- X return status;
- X}
- X
- X/*
- X * Reject articles. This can be arbitrarily picky.
- X */
- Xint
- Xreject(hdrs)
- Xregister struct headers *hdrs;
- X{
- X if (alreadyseen(hdrs->h_msgid)) {
- X timestamp(stdout, (time_t *)NULL, (char **)NULL);
- X (void) printf(" refused %s duplicate\n", hdrs->h_msgid);
- X } else if (!ngmatch(oursys()->sy_ngs, hdrs->h_ngs)) {
- X timestamp(stdout, (time_t *)NULL, (char **)NULL);
- X (void) printf(" refused %s bad groups in %s\n",
- X hdrs->h_msgid, hdrs->h_ngs);
- X } else if (moderated(hdrs) && hdrs->h_approved == NULL) {
- X timestamp(stdout, (time_t *)NULL, (char **)NULL);
- X (void) printf(" refused %s unapproved article in moderated group(s) %s\n",
- X hdrs->h_msgid, hdrs->h_ngs);
- X } else
- X return ST_OKAY;
- X if (remote) /* TODO: test this some other way */
- X return ST_NUKED;
- X else
- X return ST_NUKED|ST_DROPPED; /* more serious if local */
- X}
- X
- X/*
- X * Remove hdrs->h_files (permanent names) and h_tmpf (temporary names),
- X * and return assigned article numbers.
- X */
- Xuninsart(hdrs)
- Xregister struct headers *hdrs;
- X{
- X if (hdrs->h_unlink && hdrs->h_tmpf[0] != '\0') { /* temp name */
- X (void) unlink(hdrs->h_tmpf); /* I don't wanna know... */
- X hdrs->h_unlink = NO;
- X }
- X (void) snuffmayreturn(hdrs->h_files, YES);
- X}
- X
- Xint
- Xsnufffiles(filelist) /* just unlink all files in filelist */
- Xchar *filelist;
- X{
- X return snuffmayreturn(filelist, NO);
- X}
- X
- Xint
- Xsnuffmayreturn(filelist, artret) /* unlink all files in filelist (return artids?) */
- Xchar *filelist;
- Xint artret;
- X{
- X register char *arts, *spacep, *slashp;
- X int status = ST_OKAY;
- X char artnm[MAXFILE];
- X
- X /* this is a deadly tedious job and I really should automate it */
- X for (arts = filelist; arts != NULL && arts[0] != '\0';
- X arts = (spacep == NULL? NULL: spacep+1)) {
- X spacep = index(arts, ' ');
- X if (spacep != NULL)
- X spacep[0] = '\0'; /* will be restored below */
- X (void) strcpy(artnm, arts);
- X if (spacep != NULL)
- X spacep[0] = ' '; /* restore space */
- X
- X slashp = index(artnm, FNDELIM);
- X if (slashp != NULL)
- X slashp[0] = '\0'; /* will be restored below */
- X if (artret)
- X (void) prevartnum(artnm); /* return assigned # */
- X if (slashp != NULL)
- X slashp[0] = FNDELIM; /* restore slash */
- X
- X mkfilenm(artnm);
- X if (unlink(artnm) < 0) { /* remove a link & hope */
- X (void) fprintf(stderr, "%s: can't unlink %s\n",
- X progname, artnm);
- X status |= ST_ACCESS;
- X }
- X }
- X return status;
- X}
- END_OF_FILE
- if test 7574 -ne `wc -c <'rnews/procart.c'`; then
- echo shar: \"'rnews/procart.c'\" unpacked with wrong size!
- fi
- # end of 'rnews/procart.c'
- fi
- if test -f 'rnews/sys.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'rnews/sys.c'\"
- else
- echo shar: Extracting \"'rnews/sys.c'\" \(6730 characters\)
- sed "s/^X//" >'rnews/sys.c' <<'END_OF_FILE'
- X/*
- X * news sys file reading functions (in-memory version)
- X */
- X
- X#include <stdio.h>
- X#include <ctype.h>
- X#include <sys/types.h>
- X#include <sys/stat.h>
- X#include "news.h"
- X#include "newspaths.h"
- X#include "system.h"
- X
- Xstatic FILE *fp = NULL; /* descriptor for libfile("sys") */
- Xstatic char filerelname[] = "sys";
- X
- Xstatic struct system *firstsys = NULL; /* cache */
- Xstatic struct system *currsys = NULL; /* current system */
- X
- X/* forward decls */
- Xchar *parsecolon();
- X
- Xstruct system *
- Xoursys() /* return our sys entry */
- X{
- X register struct system *sys;
- X static struct system fakesys;
- X static struct system *thissys = NULL;
- X
- X if (thissys != NULL) /* in-core-only optimisation */
- X return thissys;
- X rewsys();
- X while ((sys = nextsys()) != NULL && !STREQ(sys->sy_name, hostname()))
- X ;
- X if (sys == NULL) { /* no entry; cook one up */
- X /* TODO: test this by some other means instead */
- X if (!remote) /* no -p, local posting */
- X (void) fprintf(stderr,
- X "%s: no %s file - your news will not leave this machine\n",
- X progname, libfile(filerelname));
- X fakesys.sy_name = hostname();
- X fakesys.sy_ngs = "all";
- X fakesys.sy_flags = 0;
- X fakesys.sy_lochops = 0;
- X fakesys.sy_cmd = "";
- X fakesys.sy_next = NULL;
- X sys = &fakesys;
- X }
- X thissys = sys; /* for future reference */
- X return sys;
- X}
- X
- X/*
- X * Returned pointer points at a static struct whose members
- X * point at static storage.
- X */
- Xstruct system *
- Xnextsys() /* return next sys entry */
- X{
- X struct system *retsys;
- X
- X if (firstsys == NULL && fp == NULL)
- X if ((fp = fopenwclex(libfile(filerelname), "r")) == NULL)
- X return NULL;
- X if (fp != NULL && firstsys == NULL) /* file open, no cache */
- X readsys(); /* read & parse fp */
- X retsys = currsys; /* save current ptr. */
- X if (currsys != NULL)
- X currsys = currsys->sy_next; /* advance current ptr. */
- X return retsys;
- X}
- X
- Xrewsys()
- X{
- X currsys = firstsys;
- X}
- X
- Xstatic char *curr, *next; /* parsing state */
- X
- XSTATIC
- Xreadsys()
- X{
- X register char *sysline;
- X
- X rewind(fp);
- X /* read possibly continued lines of arbitrary length */
- X while ((sysline = cfgetms(fp)) != NULL) {
- X if (sysline[0] != '#' && sysline[0] != '\n') { /* not a comment */
- X register struct system *sysp;
- X register char *slashp;
- X char *flagstring;
- X
- X /* This storage is never freed. */
- X sysp = (struct system *) malloc(sizeof *sysp);
- X if (sysp == NULL)
- X errunlock("out of memory for system structs", "");
- X
- X /* parse into sysp */
- X trim(sysline);
- X next = sysline;
- X parse(&sysp->sy_name);
- X parse(&sysp->sy_ngs);
- X parse(&flagstring);
- X parse(&sysp->sy_cmd);
- X /* could check for extra fields here */
- X
- X parseflags(flagstring, sysp);
- X free(flagstring); /* malloced by parse */
- X sysp->sy_next = NULL;
- X
- X /* reparse for embedded slashes */
- X slashp = index(sysp->sy_name, '/');
- X if (slashp != NULL) { /* parse name/excl1,excl2,... */
- X *slashp = '\0'; /* terminate name */
- X sysp->sy_excl = slashp + 1;
- X } else
- X sysp->sy_excl = NULL; /* no exclusions */
- X slashp = index(sysp->sy_ngs, '/');
- X if (slashp != NULL) { /* parse ngs/distrs */
- X *slashp = '\0'; /* terminate ngs */
- X sysp->sy_distr = slashp + 1;
- X } else
- X sysp->sy_distr = sysp->sy_ngs;
- X
- X /* expand ME if any */
- X if (STREQ(sysp->sy_name, "ME")) {
- X free(sysp->sy_name); /* malloced by parse */
- X sysp->sy_name = hostname(); /* NB not malloced */
- X }
- X
- X /* fill in any defaults */
- X
- X /*
- X * If no batch file name was given, use the default
- X * ($NEWSCTL/batch/b.system/togo).
- X */
- X if (sysp->sy_flags&FLG_BATCH && sysp->sy_cmd[0] == '\0') {
- X char *deffile = emalloc((unsigned)STRLEN("batch/b.") +
- X strlen(sysp->sy_name) + STRLEN("/togo") + 1);
- X
- X (void) strcpy(deffile, "batch/b.");
- X (void) strcat(deffile, sysp->sy_name);
- X (void) strcat(deffile, "/togo");
- X free(sysp->sy_cmd); /* malloced by parse */
- X sysp->sy_cmd = libfile(deffile); /* NB not malloced */
- X free(deffile);
- X }
- X /*
- X * If no command was given, use the default
- X * (uux - -r -z system!rnews).
- X * (This *is* yucky and uucp-version-dependent.)
- X */
- X if (!(sysp->sy_flags&FLG_BATCH) && sysp->sy_cmd[0] == '\0') {
- X /* TODO: send mail to usenet, harassing him. */
- X /* TODO: search PATH including $NEWSCTL/syscmd */
- X free(sysp->sy_cmd); /* malloced by parse */
- X sysp->sy_cmd = emalloc((unsigned)STRLEN("uux - -r -z ") +
- X strlen(sysp->sy_name) + STRLEN("!rnews") + 1);
- X (void) strcpy(sysp->sy_cmd, "uux - -r -z ");
- X (void) strcat(sysp->sy_cmd, sysp->sy_name);
- X (void) strcat(sysp->sy_cmd, "!rnews");
- X }
- X
- X /* stash *sysp away on the tail of the current list */
- X if (firstsys == NULL)
- X firstsys = sysp; /* 1st system */
- X else
- X currsys->sy_next = sysp; /* tack on tail */
- X currsys = sysp;
- X }
- X free(sysline);
- X }
- X (void) fclose(fp); /* file no longer needed */
- X fp = NULL; /* mark file closed */
- X rewsys();
- X}
- X
- XSTATIC
- Xparse(into)
- Xregister char **into;
- X{
- X curr = next;
- X if (curr == NULL)
- X *into = strsave("");
- X else {
- X next = parsecolon(curr);
- X *into = strsave(curr);
- X }
- X /* *into is never freed. */
- X if (*into == NULL)
- X errunlock("out of memory for sys strings", "");
- X}
- X
- XSTATIC char *
- Xparsecolon(line) /* return NULL or ptr. to byte after colon */
- Xchar *line;
- X{
- X register char *colon;
- X
- X INDEX(line, ':', colon);
- X if (colon != NULL)
- X *colon++ = '\0'; /* turn colon into a NUL */
- X return colon;
- X}
- X
- XSTATIC
- Xparseflags(flags, sysp)
- Xregister char *flags; /* flags string */
- Xregister struct system *sysp; /* result here */
- X{
- X sysp->sy_flags = 0;
- X sysp->sy_lochops = 0; /* default L value */
- X for (; *flags != '\0'; flags++)
- X switch (*flags) {
- X case 'A':
- X errunlock("A news format not supported", "");
- X /* NOTREACHED */
- X case 'B': /* mostly harmless */
- X break;
- X case 'f':
- X sysp->sy_flags |= FLG_SZBATCH;
- X break;
- X case 'F':
- X sysp->sy_flags |= FLG_BATCH;
- X break;
- X case 'I': /* NNTP */
- X /* TODO: I sys flag: I-have, write msg-ids */
- X break;
- X case 'L': /* Ln */
- X sysp->sy_flags |= FLG_LOCAL;
- X sysp->sy_lochops = 0;
- X if (isascii(flags[1]) && isdigit(flags[1])) {
- X sysp->sy_lochops *= 10;
- X sysp->sy_lochops += *++flags - '0';
- X }
- X break;
- X case 'm':
- X /* TODO: m sys flag: send only moderated groups */
- X break;
- X case 'N':
- X sysp->sy_flags |= FLG_IHAVE;
- X errunlock("N flag given but I-have/send-me is not supported", "");
- X /* NOTREACHED */
- X case 'u':
- X /* TODO: u sys flag: send only unmoderated groups */
- X break;
- X case 'U': /* mostly harmless */
- X /* sysp->sy_flags |= FLG_PERM; */
- X break;
- X case 'H': /* bugger off */
- X case 'S': /* bugger off */
- X case 'M': /* multicast: obs., see batcher */
- X case 'O': /* multicast: obs., see batcher */
- X default:
- X errunlock("unknown sys flag `%c' given", *flags);
- X /* NOTREACHED */
- X }
- X}
- END_OF_FILE
- if test 6730 -ne `wc -c <'rnews/sys.c'`; then
- echo shar: \"'rnews/sys.c'\" unpacked with wrong size!
- fi
- # end of 'rnews/sys.c'
- fi
- echo shar: End of archive 9 \(of 14\).
- ## End of shell archive.
- exit 0
-